-- Co-ords to track current location. Start point is always 0,0,0 and
-- current location is relative to this. If you're the turtle, then
-- X is left (-) or right (+)
-- Y is down (-) or up (+)
-- Z is forward (+) or back (-)
local currentX=0
local currentY=0
local currentZ=0

local counter = 0 -- Used to control how often we send a rednet message out updating our position - only send every 10 moves

-- Orientation, where 0=N, 1=E, 2=S, 3=W
-- NOTE: Throughout this program, N is considered forward as from the starting position, not
-- necessarily 'compass north' in Minecraft
orient=0

refuelLevel = 100
invSlots = 16
fullflag = false
needfuelflag = false
status = "inactive" -- default turtle status to inactive

function setRefuelLevel(i)
	refuelLevel = i
end

function getRefuelLevel()
	return refuelLevel
end

function setActive() status = "active" end
function setInactive() status = "inactive" end
function setBlocked() status = "blocked" end
function setFuel() status = "fuel" end
function setFull() status = "full" end
function setFinished() status = "finished" end

function getStatus()
	return status
end

-- Saves the given co-ordinates to a file for recovery later
function saveCoords(x,y,z)
	if not fs.isDir("/save") then fs.makeDir("/save") end
	local xfile=io.open("/save/posx","w")
	xfile:write(x)
	xfile:close()
	local yfile=io.open("/save/posy","w")
	yfile:write(y)
	yfile:close()
	local zfile=io.open("/save/posz","w")
	zfile:write(z)
	zfile:close()
end

-- Retrieves the saved co-ordinates and returns them as 3 parameters
function loadCoords()
	if (not fs.exists("/save/posx")) or (not fs.exists("/save/posy")) or (not fs.exists("/save/posz")) then return false,false,false end
	local xfile=io.open("/save/posx","r")
	local x = tonumber(xfile:read())
	xfile:close()
	local yfile=io.open("/save/posy","r")
	local y = tonumber(yfile:read())
	yfile:close()
	local zfile=io.open("/save/posz","r")
	local z = tonumber(zfile:read())
	zfile:close()
	logger.debug("Loaded from disk : "..x..","..y..","..z)
	return x,y,z
end

function saveStart(x,y,z)
	if type(x)=="number" and type(y)=="number" and type(z)=="number" then
		if not fs.isDir("/save") then fs.makeDir("/save") end
		local xfile=io.open("/save/startx","w")
		xfile:write(x)
		xfile:close()
		local yfile=io.open("/save/starty","w")
		yfile:write(y)
		yfile:close()
		local zfile=io.open("/save/startz","w")
		zfile:write(z)
		zfile:close()
	end
end

-- Retrieves the saved co-ordinates and returns them as 3 parameters
function loadStart()
	if (not fs.exists("/save/startx")) or (not fs.exists("/save/starty")) or (not fs.exists("/save/startz")) then return false,false,false end
	local xfile=io.open("/save/startx","r")
	local x = tonumber(xfile:read())
	xfile:close()
	local yfile=io.open("/save/starty","r")
	local y = tonumber(yfile:read())
	yfile:close()
	local zfile=io.open("/save/startz","r")
	local z = tonumber(zfile:read())
	zfile:close()
	logger.debug("Loaded from disk : "..x..","..y..","..z)
	return x,y,z
end

function saveTable(t,fname)
	if not fs.isDir("/save") then fs.makeDir("/save") end
	local tfile = io.open("/save/"..fname,"w")
	tfile:write(textutils.serialize(t))
	tfile:close()
end

function loadTable(fname)
	if not fs.exists("/save/"..fname) then return false end
	local tfile = io.open("/save/"..fname,"r")
	local t = tfile:read()
	tfile:close()
	return textutils.unserialize(t)
end

function clearCoords()
	fs.delete("/save/posx")
	fs.delete("/save/posy")
	fs.delete("/save/posz")
end

function clearStart()
	fs.delete("/save/startx")
	fs.delete("/save/starty")
	fs.delete("/save/startz")
end

function clearTable(fname)
	fs.delete("/save/"..fname)
end

function sendPosUpdate()
	counter = counter + 1
	if counter>10 then
		logger.xmit()
		counter = 0
	end
end

function getCurrentPos()
	return currentX, currentY, currentZ
end

function setCurrentPos(x,y,z)
	currentX = x
	currentY = y
	currentZ = z
	logger.debug("Current position forcibly set to "..x..","..y..","..z)
end

-- Checks current fuel level. If lower than refuelLevel, will attempt to refuel from
-- inventory until its fuel level is greater than twice the refuelLevel value. Returns the remaining
-- fuel level (movements left). If we've got no fuel left to source from then we 
-- return false. Note this checks all slots, not just the fuel slot #1, since we might pick up fuel
-- along the way (coal being a prime example)... might as well use it :)
function fuelcheck()
	local startLevel=turtle.getFuelLevel()
	if startLevel<refuelLevel then
		-- Need to refuel
		local i = 1
		while (turtle.getFuelLevel()<(2*refuelLevel) and i<=invSlots) do
			turtle.select(i)
			if not turtle.refuel(1) then
				-- No fuel in this slot; move on to the next one and re-attempt refuel
				i=i+1
			end
		end
		if (i>invSlots) then
			print("No more fuel in inventory; return to refuel")
			return 0
		end
		return turtle.getFuelLevel()
	else
		-- We've got plenty of fuel so just return the current fuel level
		return startLevel
	end
end

-- Returns count of number of empty slots in inventory, ignoring slot 1 which is reserved for fuel
function numEmptySlots()
	local result = 0
	for i = 2, invSlots, 1 do
		if turtle.getItemCount(i)==0 then
			result = result + 1
		end
	end
	return result
end

-- Returns count of total number of items in inventory, excluding slot 1 which is for fuel
function stockTake()
	local result = 0
	for i= 2, invSlots, 1 do
		result=result+turtle.getItemCount(i)
	end
	return result
end

-- Empties all slots
function dumpLoad()
-- Never dump slot 1 - that's where we keep our fuel!
	for i = 2, invSlots, 1 do
		turtle.select(i)
		turtle.drop()
	end
	logger.info("Unloaded inventory to home")
end

function getFuel()
-- Assumes we are at home (0,0) and stock up on fuel into slot 1.
-- Fuel is expected in an inventory above the turtle while at it's home position
	turtle.select(1)
	if (turtle.getItemCount(1)>0) then
		-- We've still got some fuel in slot 1, so let's dump it into the inventory
		-- before we pull some more form it - this will automatically consolidate the
		-- fuel in the chest for us
		turtle.dropUp()
	end
	
	if not turtle.suckUp() then
		logger.crit("Could not collect fuel from home")
		return false
	else
		logger.info("Collected additional fuel")
		return true
	end
	
end

-- Set the orient variable based on a turn left or right
function turnR() -- turn right
	turtle.turnRight()
	if orient == 3 then
		orient = 0
	else
		orient = orient + 1
	end
end

function turnL() -- turn left
	turtle.turnLeft()
	if orient == 0 then
		orient = 3
	else
		orient = orient - 1
	end
end

-- Orient the turtle to a given direction, where
-- 0=N
-- 1=E
-- 2=S
-- 3=W
function orientMe(target)

	if (orient==0 and target==3) then
		turnL()
	elseif (orient==3 and target==0) then
		turnR()
	else
		turns = target - orient
		for i = 1, math.abs(turns), 1 do
			if turns < 0 then
				turnL()
			elseif turns > 0 then
				turnR()
			end
		end
	end
end

-- moveBack moves the turtle backwards, mining anything in it's way if it can.
-- It maintains orientation, leaving the turtle facing the way it did before the call
-- Returns <boolean>
-- ...where <boolean> is true if move completed, otherwise false
function moveBack()

	local result
	local reason = ""
	
	if not turtle.back() then
		-- We couldn't move, so let's spin round, try to mine it, and see if that gets us anywhere!
		turnL()
		turnL()
		result, reason = mineIntoInventory(0)
		if result then
			if turtle.forward() then
				turnR()
				turnR()
			else
				-- Odd - mined successfully but now we can't move. Maybe blocked by mob?
				turnR()
				turnR()
				logger.warn("moveBack() mined, but failed to move - blocked by mob?")
				return false, "blocked" -- We didn't move
			end
		else
			-- We couldn't mine it, so we couldn't move backwards. Turn us back...
			turnR()
			turnR()
			logger.warn("moveBack() couldn't mine a block : "..reason)
			return false, reason -- We didn't move
		end
	end

	if orient==0 then
		currentZ=currentZ-1
	elseif orient==1 then
		currentX=currentX-1
	elseif orient==2 then
		currentZ=currentZ+1
	else
		currentX=currentX+1
	end
	
	saveCoords(currentX,currentY,currentZ)
	sendPosUpdate()
	return true,reason -- The move back worked first time

end

-- moveForward moves the turtle forwards, mining anything in it's way if it can.
function moveForward()
	
	local result
	local reason = ""
	
	-- First just try moving forward - it might be clear after all
	if not turtle.forward() then
		-- TODO: Detect - do we detect a block in the way? If so, try to mine it. If not, then we must be blocked
		-- by a mob so attempt to clear it by attacking it.
		
		-- It's not, so let's mine the block away
		result, reason = mineIntoInventory(0)
		if not result then
			-- Couldn't mine the block, so that's it, we're done - we can't move forward
			logger.warn("moveForward() couldn't mine a block : "..reason)
			return false, reason
		else
			if not turtle.forward() then
				-- Odd - we mined it, it should be clear, but we failed to move forward. Maybe blocked by mob?
				-- TODO : Attack mobs and re-try move?
				logger.warn("moveForward() mined, but failed to move - blocked by mob?")
				return false, "blocked"
			end
		end
	end
	
	if orient==0 then
		currentZ=currentZ+1
	elseif orient==1 then
		currentX=currentX+1
	elseif orient==2 then
		currentZ=currentZ-1
	else
		currentX=currentX-1
	end
	
	saveCoords(currentX,currentY,currentZ)
	sendPosUpdate()
	return true,reason

end

-- moveUp moves the turtle upwards, mining anything in it's way if it can.
function moveUp()

	local result
	local reason = ""
	
	-- First just try moving forward - it might be clear after all
	if not turtle.up() then
		-- It's not, so let's mine the block away
		result, reason = mineIntoInventory(2)
		if not result then
			-- Couldn't mine the block, so that's it, we're done - we can't move up
			logger.warn("moveUp() couldn't mine a block : "..reason)
			return false, reason
		else
			if not turtle.up() then
				-- Odd - we mined it, it should be clear, but we failed to move up. Maybe blocked by mob?
				logger.warn("moveUp() mined, but failed to move - blocked by mob?")
				return false, "blocked"
			end
		end
	end
	
	currentY=currentY+1
	
	saveCoords(currentX,currentY,currentZ)
	sendPosUpdate()
	return true,reason

end

-- moveDown moves the turtle downwards, mining anything in it's way if it can.
function moveDown()
	
	local result
	local reason = ""

	-- First just try moving forward - it might be clear after all
	if not turtle.down() then
		-- It's not, so let's mine the block away
		result, reason = mineIntoInventory(1)
		if not result then
			-- Couldn't mine the block, so that's it, we're done - we can't move down
			logger.warn("moveDown() couldn't mine a block : "..reason)
			return false, reason
		else
			if not turtle.down() then
				-- Odd - we mined it, it should be clear, but we failed to move down. Maybe blocked by mob?
				logger.warn("moveUp() mined, but failed to move - blocked by mob?")
				return false, "blocked"
			end
		end
	end
	
	currentY=currentY-1
	
	saveCoords(currentX,currentY,currentZ)
	sendPosUpdate()
	return true,reason

end

-- Move the turtle along the X axis to a certain point, mining all in its path. tox is relevant to 0 (home).
-- Returns :
--  <boolean> result 				- indicating whether the turtle moved or not
--  [string] failure reason	- reason why it failed to move ("fuel","blocked")
function moveX(tox)

	local result, reason = ""
	
	if (fuelcheck()==0) then reason="fuel" else reason="" end
		
	if tox > currentX then
		orientMe(1) -- Face east
		while currentX<tox do
			result, reason = moveForward()
			if not result then 
				-- Why did we fail to move? It's either because we're blocked or we're out of fuel, so check fuel - if
				-- that's zero it's the reason why, otherwise it's safe to assume we were blocked.
				if turtle.getFuelLevel()==0 then
					logger.crit("moveX(): out of fuel")
					return false,"fuel"
				else
					return false,reason
				end
			end
		end
		return true,reason
	elseif tox < currentX then
		orientMe(3) -- Face west
		while currentX>tox do
			result, reason = moveForward()
			if not result then 
				-- Why did we fail to move? It's either because we're blocked or we're out of fuel, so check fuel - if
				-- that's zero it's the reason why, otherwise it's safe to assume we were blocked.
				if turtle.getFuelLevel()==0 then
					logger.crit("moveX(): out of fuel")
					return false,"fuel"
				else
					return false,reason
				end
			end
		end
		return true,reason
	else
		-- We're already there!
		return true,reason
	end
end

-- Move the turtle along the Y axis to a certain point, mining all in its path. toy is relevant to 0 (home).
-- Will terminate returning false if for any reason it cannot move (which may happen, particularly going down and hitting bedrock)
function moveY(toy)

	local result, reason = ""
	if (fuelcheck()==0) then reason="fuel" else reason="" end

	if toy > currentY then
		while currentY<toy do
			result, reason = moveUp()
			if not result then 
				-- Why did we fail to move? It's either because we're blocked or we're out of fuel, so check fuel - if
				-- that's zero it's the reason why, otherwise it's safe to assume we were blocked.
				if turtle.getFuelLevel()==0 then
					logger.crit("moveY(): out of fuel")
					return false,"fuel"
				else
					return false,reason
				end
			end
		end
		return true,reason
	elseif toy < currentY then
		while currentY>toy do
			result, reason = moveDown()
			if not result then 
				-- Why did we fail to move? It's either because we're blocked or we're out of fuel, so check fuel - if
				-- that's zero it's the reason why, otherwise it's safe to assume we were blocked.
				if turtle.getFuelLevel()==0 then
					logger.crit("moveY(): out of fuel")
					return false,"fuel"
				else
					return false,reason
				end
			end
		end
		return true,reason
	else
		-- We're already there!
		return true,reason
	end
end

-- Move the turtle along the Z axis to a certain point, mining all in its path. toz is relevant to 0 (home).
function moveZ(toz)

	local result, reason = ""
	if (fuelcheck()==0) then reason="fuel" else reason="" end

	if toz > currentZ then
		orientMe(0) -- face North
		while currentZ<toz do
			result, reason = moveForward()
			if not result then 
				-- Why did we fail to move? It's either because we're blocked or we're out of fuel, so check fuel - if
				-- that's zero it's the reason why, otherwise it's safe to assume we were blocked.
				if turtle.getFuelLevel()==0 then
					logger.crit("moveZ(): out of fuel")
					return false,"fuel"
				else
					return false,reason
				end
			end
		end
		return true,reason
	elseif toz < currentZ then
		orientMe(2) -- face South
			while currentZ>toz do
				result, reason = moveForward()
				if not result then 
					-- Why did we fail to move? It's either because we're blocked or we're out of fuel, so check fuel - if
					-- that's zero it's the reason why, otherwise it's safe to assume we were blocked.
					if turtle.getFuelLevel()==0 then
						logger.crit("moveZ(): out of fuel")
						return false,"fuel"
					else
						return false,reason
					end
				end
			end
		return true,reason
	else
		-- We're already there!
		return true,reason
	end
end


-- Send the turtle to a particular point in space with the following strategy...
-- 1) Do depth (Y) first
-- 2) Do across (X) next
-- 3) Do across (Z) next
-- Mine everything along the way, if possible
-- EXTRA: Only make the journey if there is enough fuel in the turtle to do it
function gotoXYZ(tox, toy, toz)
	local fcresult
	while turtle.getFuelLevel() < (tox+toy+toz) do
		fcresult = fuelcheck()
		if fcresult==0 then
			-- If fuelcheck spits us back 0, it's advising us that we've got no fuel left in our inventory, so we should
			-- prioritise getting back to home ASAP to refuel. Therefore abort the call to gotoXYZ immediately.
			return false,"fuel"
		end
	end
	
	local yresult, reason = moveY(toy)
	if not yresult then return false, reason end
	local xresult, reason = moveX(tox)
	if not xresult then return false, reason end
	local zresult, reason = moveZ(toz)
	if not zresult then return false, reason end
	
	return true,reason
	
end

-- Send the turtle to a particular point in space with the following strategy...
-- 1) Do across (Z) first
-- 2) Do across (X) next
-- 3) Do depth (Y) next
-- Mine everything along the way, if possible. Don't worry about a fuel check to see if we can get there; the intention is that this
-- call is used for a return journey back towards home, so the turtle should always attempt the trip even if it's low on fuel
function returnXYZ(tox, toy, toz)
	local xresult, reason = moveX(tox)
	if (not xresult) then return false, reason end
	local zresult, reason = moveZ(toz)
	if (not zresult) then return false, reason end
	local yresult, reason = moveY(toy)
	if (not yresult) then return false, reason end

	return true,reason
	
end

-- Mines an area along the X/Z axes (ie. only 1 block high, but 'lengthX'/'lengthZ' blocks wide and long)
-- with the origin of the square at startX/startZ for the purposes of measuring the length/width.
-- You can start the turtle off in the middle, for the purposes of re-commencing, for example.
-- Returns true if it completed the square, false if it could not finish it (full, or non-mineable blocks), plus X & Z co-ordinates of where the
--  turtle was if it aborted. This is so it can resume there next trip down.
function mineRectangle(lengthX, lengthZ, startX, startZ)

	local deltaX = 0 -- Used to store the current X offset from the start corner of the rectangle
	local deltaZ = 0 -- Used to store the current Z offset from the start corner of the rectangle
	local finished = false -- Flags when we've completed the rectangle
	local breakout = false -- Flags if there's a problem and we can't complete the rectangle; used to abort
	local result = nil
	local reason = nil
	
	if currentZ>=startZ or currentX>=startX then
		logger.debug("Commencing rectangle at "..currentX..","..currentZ)
	elseif currentZ<startZ or currentX<startX then
		logger.debug("Moving turtle into area")
	end

	deltaX=currentX-startX
	deltaZ=currentZ-startZ

	-- Main loop. Breakout conditions :-
	-- 1) We're full
	-- 2) We've finished mining the entire rectangle
	-- 3) We can't mine through a particular block (bedrock/unmineable for some reason)
	while ((not finished) and (not breakout)) do
		
		-- Perform a north/south run...
		while ((currentX<(startX+lengthX)) and (not breakout)) do
			-- This figures out which run it's doing (north on Z, or south on Z) based on X
			--  If x=0,2,4,6,8,etc then it should do a northward run
			--  If x=1,3,5,7,9,etc then it should do a southward run
			if (math.fmod(currentX-startX,2)==0) then
				-- Even X co-ordinate, so do the run northbound (start Z at 0 and run to lengthZ)
				while (currentZ<startZ+lengthZ and (not breakout)) do	
					result, reason = moveZ(currentZ+1)
					if (not result) or (type(reason)=="string" and string.len(reason)>0) then
						-- Failed to move north; abort
						breakout=true
					end
				end
			else
				-- Odd X co-ordinate, so do the run southbound (start Z at lengthZ and run to 0)
				while (currentZ>startZ and (not breakout)) do
					result, reason = moveZ(currentZ-1)
					if (not result) or (type(reason)=="string" and string.len(reason)>0) then
						-- Failed to move south; abort
						breakout=true
					end
				end
			end
			-- Move along the X axis as needed
			if not breakout then
				if (currentX<(startX+lengthX)) then
					result, reason = moveX(currentX+1)
					if (not result) or (type(reason)=="string" and string.len(reason)>0) then
						-- Failed to move across; abort
						breakout=true
					end
					finished=true
				else
					finished=true
				end
			end
			
		end -- while for north/south run
	end -- while for whole rectangle

	-- Return to the start corner of the square
	deltaX=currentX
	deltaZ=currentZ
	local reasonc -- Need to use a separate var to store reason this time, because we need to keep the previous ('reason') for the return from the function
	result, reasonc = moveX(startX)
	if not result then
		-- Oh bugger. We can't get back, most likely because we're out of fuel. Refuel level was probably set too low.
		return false, reasonc, currentX, currentZ
	end
	result, reasonc = moveZ(startZ)
	if not result then
		-- Oh bugger. We can't get back, most likely because we're out of fuel. Refuel level was probably set too low.
		return false, reasonc, currentX, currentZ
	end
	
	if breakout then
		-- Why did we breakout? If it's because we're full or low on fuel, then we need to
		-- indicate that this isn't a 'hard' failure - we can come back and resume once we've returned to base
		logger.debug("mineRectangle exiting with false,"..reason..","..deltaX..","..deltaZ)
		return false,reason,deltaX,deltaZ
	else
		logger.debug("mineRectangle completed")
		return true,"",startX,startZ -- If we dug out the square, return true, otherwise return false
	end
end

-- Mines a complete 3D 'cuboid' rea of given edge length and height with the turtle starting in the
-- SW corner (assuming the way it is facing is north). Can pick up work at an offset inside (startX/startY/startZ) -
-- used if we're commencing this area from a saved position or after a refuel/item drop back at home.
-- Returns true if it completed the area, false if it could not finish it (full, or non-mineable blocks), plus X /Y/Z co-ordinates of where the
-- turtle was if it aborted. This is so it can resume there next trip down.
function mineCuboid(width, height, startX, startY, startZ)

	local targetY = startY+height
	local deltaX
	local deltaZ
	local breakout = false -- Flags if there's a problem and we can't complete the area; used to abort
	local result = nil
	local reason = nil
	
	if currentX>=startX or currentY~=startY or currentZ>=startZ then
		-- We are not at the origin of the cuboid - we're resuming somewhere within it
		-- probably from a refuel/load dump or else a world reload.
		logger.debug("Commencing cuboid at "..currentX..","..currentY..","..currentZ)
	elseif currentX<startX or currentZ<startZ then
		logger.debug("Moving turtle into cube area")
		gotoXYZ(startX,currentY,startZ) -- Just a safety check in case someone calls the function while the turtle isn't in the cube area
	end
	
	-- Main loop. Breakout conditions :-
	-- 1) We're full
	-- 2) We've finished mining the entire area
	-- 3) We can't mine through a particular block (bedrock/unmineable for some reason)
	-- Move to appropriate height and mine a square at that level
	while (currentY~=targetY and (not breakout)) do

		result, reason, deltaX, deltaZ = mineRectangle(math.abs(width), math.abs(width), startX, startZ)
		if (not result) or (type(reason)=="string" and string.len(reason)>0) then
			-- Failed to mine at rectangle at this height; abort
			breakout=true
		else
			-- Move up or down as necessary
			if targetY>currentY then
				-- Move upwards
				result, reason = moveY(currentY+1)
			elseif targetY<currentY then
				-- Move downwards
				result, reason = moveY(currentY-1)
			end
			if (not result) or (type(reason)=="string" and string.len(reason)>0) then breakout=true	end
		end
	end -- while
	
	if breakout then
		-- X/Z-wise we're in the right place (mineRectangle takes care of returning us), but we do need to move up/down to the original height...
		local tresult, treason = moveY(startY)
		if not tresult then
			logger.debug("mineCuboid() failed to move on Y: "..treason.." @ "..currentX..","..currentY..","..currentZ)
			return false,treason,currentX,currentY,currentZ -- return the reason why we couldn't get back to 0,0,0
		else
			logger.debug("mineCuboid() failed : "..reason.." @ "..deltaX..","..currentY..","..deltaZ)
			return false,reason,deltaX,currentY,deltaZ -- return the reason why the mining of the cuboid failed, and the position where we got to when we stopped
		end
	end
		
	-- The only way we're reaching here is if we finished successfully, so...
	-- Return to the start corner
	local tresult, treason = returnXYZ(startX,startY,startZ)
	if (not tresult) then
		-- Oh this isn't good. We can't even get back to the start
		logger.debug("mineCuboid() failed to return home: "..treason.." @ "..currentX..","..currentY..","..currentZ)
		return false,treason,currentX,currentY,currentZ
	else
		logger.debug("minecuboid() completed : "..treason.." @ 0,0,0")
		return true,treason,0,0,0
	end
	
end

-- Dir(ection) : 0=forward, 1=down, 2/anything else=up
-- Mines in the specified direction, if necessary, taking the item into the turtle's inventory.
-- Will repeat mining as needed, until there is no block detected or the turtle fills up.
-- Returns true if the mine succeeded, or if there is no block to mine
-- Returns false if the dig failed to break/mine the block (eg. bedrock)
function mineIntoInventory(dir)

	local foundSlot = false
	local digFailed = false
	turtle.select(2)
	
	if dir==0 then
		while turtle.detect() do
			if not turtle.dig() then
				return false, "blocked"
			end
			sleep(0.5) -- Needed to allow sand to fall, for example
		end
	elseif dir==1 then
		while turtle.detectDown() do
			if not turtle.digDown() then
				return false, "blocked"
			end
			sleep(0.5) -- Needed to allow sand to fall, for example
		end
	else
		while turtle.detectUp() do
			if not turtle.digUp() then
				return false, "blocked"
			end
			sleep(0.5) -- Needed to allow sand to fall, for example
		end
	end
	
	-- We mined the block. We do inventory checking here, reporting if we're full
	if numEmptySlots()==0 then
		-- No more slots available, so we *could* potentially miss a block if we mined it. So report as full -
		-- if we missed something like diamonds because we had no spare slot, we'd be pretty peeved :)
		print("Full!")
		return true,"full"
	else
		return true,""
	end
		
end